package com.csjy.migration.hnnd;

import com.csjy.migration.hnnd.annotation.BusinessDataConverter;
import com.csjy.migration.hnnd.business.AbstractBusiness;
import com.csjy.migration.hnnd.business.AbstractWorkflowBusiness;
import com.csjy.migration.hnnd.business.SourceBusinessData;
import com.csjy.migration.hnnd.workflow.WorkflowMigration;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * =======================================数据量==========================================
 * 流程定义：199 条
 * 任务定义：190 条
 * 流程实例：96,596 条
 * 任务实例：513,507 条
 * 任务实例业务数据记录: 3,251,667 （JBPM_VARIABLEINSTANCE)
 * 任务实例自定义业务数据记录：608,000（WF_AFFIX_NOTION_OBJ)
 *
 * ================================源数据有问题的数据记录======================================
 * 1.业务流程实例中间表(BT_ITEM_WORKFLOW_REC)有部分记录的流程定义名称(WFNAME)与流程定义表(JBPM_PROCESSDEFINITION)中的名称(NAME_)不一致
 *   具体不一致的流程定义ID有：728779,819397,10847227
 *   解决方法：使BT_ITEM_WORKFLOW_REC表中存储的流程定义名称与流程定义表中的名称保持一致
 *   检测sql：
 *          SELECT
 *           jp3.ID_
 *         FROM
 *           BT_ITEM_WORKFLOW_REC biwr
 *         JOIN JBPM_PROCESSINSTANCE jp2 ON biwr.workflowno = jp2.ID_
 *         JOIN JBPM_PROCESSDEFINITION jp3 ON jp2.PROCESSDEFINITION_ = jp3.ID_
 *         WHERE
 *           biwr.ITEMNO IN (SELECT ITEMNO FROM BT_ITEM_BASIC)
 *         AND
 *           biwr.WFNAME LIKE '%hny%'
 *          AND biwr.WFNAME != jp3.NAME_
 *         GROUP BY jp3.ID_
 * 业务数据迁移思路
 * 1. 一种或多种（考虑林业项目流程)流程类型对应一个迁移类，在该类中对每种任务节点类型进行独立迁移,可以有通用流程迁移类或通用任务节点类型
 * 2. 以流程类型为最基本的单位进行迁移
 * 3. 仅迁移关键业务数据，流程过程数据或条件标记等数据可忽略
 * 4. 新系统流程实例列表可以做一个通用功能：更新老系统流程实例业务数据(先在本jar中提供即可)
 *
 */
@BusinessDataConverter(
    auto= false,
    insertSql = "",
    updateSql = "",
    findMigratedIdListSql = ""
)
public class WorkflowData extends AbstractBusiness {

  public WorkflowData(DbUtil sourceDbUtil, DbUtil targetDbUtil, SourceBusinessData sourceData,
                      ProgramArgument programArgument, String projectId) throws SQLException {
    super(sourceDbUtil, targetDbUtil, sourceData, programArgument, projectId,true);
  }

  public void customMigrate(Map procInstRow) throws Exception {
    System.out.println("开始迁移流程业务数据...");
    try {
      String oldProcInstId = procInstRow.get("ID_").toString();
      if(this.programArgument.getCover().equals("0") && BusinessTool.checkMigrated(oldProcInstId + "-task-data")) {
        return;
      }

      try {
        targetDbUtil.updateByParams("DELETE FROM MIGRATION_ID_MAP WHERE SOURCE_ID = ?", Arrays.asList(new String[]{oldProcInstId + "-task-data"}));
        // 查询流程类型编码
        String oldWorkflowCode = this.getOldWorkflowCodeByOldProcInstId(procInstRow.get("WFNAME").toString());
        String className = Arrays.stream(oldWorkflowCode.split("-")).reduce("",(acc,cur)->acc+cur.substring(0,1).toUpperCase()+cur.substring(1));
        String classQualifiedName = "com.csjy.migration.hnnd.workflow." + className;
        Class<WorkflowMigration> workflowMigrationClass = (Class<WorkflowMigration>) Class.forName(classQualifiedName);
        Constructor<WorkflowMigration> ctor = workflowMigrationClass.getConstructor(DbUtil.class,DbUtil.class, SourceBusinessData.class, ProgramArgument.class
            ,String.class, String.class,Map.class);
        ctor.newInstance(sourceDbUtil,targetDbUtil,sourceData,programArgument,projectId,oldProcInstId,procInstRow).start();
        targetDbUtil.insertMigrationIdMap(oldProcInstId + "-task-data");
      } catch(Exception e){
        String errorMsg = String.format("流程[%s]的业务数据迁移失败:\n",oldProcInstId);
        if(e instanceof InvocationTargetException) {
          errorMsg = errorMsg + ((InvocationTargetException)e).getTargetException().getMessage()+"\n";
        } else {
          errorMsg = errorMsg + e.getMessage();
        }
        throw new Exception(errorMsg);
      }
      System.out.println("流程业务数据迁移完毕.");
    } catch(Exception e) {
      throw new Exception("流程业务数据迁移过程中出现异常,"+e.getMessage());
    }
  }

  /**
   * 获取老流程code
   * @param oldWorkflowCode
   * @return
   * @throws SQLException
   */
  public String getOldWorkflowCodeByOldProcInstId(String oldWorkflowCode) throws SQLException {
    // 申请利息补贴 item_ask_subsity
    oldWorkflowCode = oldWorkflowCode.replace("-liy","").replace("_","-");
    // 补交法律资料重复 item-sencor-prefix-datum-hny item-sencor-prefix-datum
    if(oldWorkflowCode.equals("item-sencor-prefix-datum")) {
      oldWorkflowCode = oldWorkflowCode + "-hny";
    }
    return oldWorkflowCode;
  }

  @Override
  public void migrate() throws Exception {

  }
}
